﻿using System;
using System.IO;
using System.Linq.Expressions;
using System.Text;

namespace Core
{
    public class GenericUtil
    {
        /// <summary>
        /// Gets the value or null.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="valueAsString">The value as string.</param>
        /// <returns></returns>
        public static T? GetValueOrNull<T>(string valueAsString) where T : struct
        {
            if (string.IsNullOrEmpty(valueAsString))
            {
                return null;
            }

            var changeType = Convert.ChangeType(valueAsString, typeof(T));
            if (changeType != null)
                return (T)changeType;

            return default(T);
        }

        /// <summary>
        /// Determines whether the specified obj is nullable.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">The obj.</param>
        /// <returns>
        /// 	<c>true</c> if the specified obj is nullable; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsNullable<T>(T obj)
        {
            if (obj == null)
                return true;

            Type type = typeof(T);

            if (!type.IsValueType)
                return true; // ref-type

            if (Nullable.GetUnderlyingType(type) != null)
                return true; // Nullable<T>

            return false; // value-type
        }

        /// <summary>
        /// Parses the specified source value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceValue">The source value.</param>
        /// <returns></returns>
        /// <example>
        /// int val = GenericUtil.Parse&lt;int&gt;("12");
        /// </example>
        public static T Parse<T>(string sourceValue) where T : IConvertible
        {
            return (T)Convert.ChangeType(sourceValue, typeof(T));
        }

        /// <summary>
        /// Parses the specified source value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceValue">The source value.</param>
        /// <param name="provider">The provider.</param>
        /// <returns></returns>
        /// <example>
        /// DateTime datetime = GenericUtil.Parse&lt;DateTime&gt;("12.10.2007");
        /// IFormatProvider providerEN = new System.Globalization.CultureInfo("en-US", true);
        /// DateTime y = GenericUtil.Parse&lt;DateTime&gt;("12.10.2007",providerEN);</example>
        public static T Parse<T>(string sourceValue, IFormatProvider provider) where T : IConvertible
        {
            return (T)Convert.ChangeType(sourceValue, typeof(T), provider);
        }

        /// <summary>
        /// Gets the type of the value from.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static T? GetValueFromType<T>(object source, T? obj) where T : struct
        {
            if (Convert.IsDBNull(source))
            {
                if (IsNullable(obj))
                {
                    return null;
                }
                if (source is DateTime)
                {
                    var changeType = Convert.ChangeType(DateTime.MinValue, typeof(T));
                    if (changeType != null)
                        return (T)changeType;
                }
                if (source is decimal || source is Int32 || source is double)
                {
                    var changeType = Convert.ChangeType("0", typeof(T));
                    if (changeType != null)
                        return (T)changeType;
                }
                var type = Convert.ChangeType("", typeof(T));
                if (type != null)
                    return (T)type;
            }
            var o = Convert.ChangeType(source, typeof(T));
            if (o != null)
                return (T)o;

            return default(T);
        }

        /// <summary>
        /// Gets the type of the value from.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">The source.</param>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static T GetValueFromType<T>(object source, T obj) where T : struct
        {
            if (source is DateTime)
            {
                var changeType = Convert.ChangeType(DateTime.MinValue, typeof(T));
                if (changeType != null)
                    return (T)changeType;
            }
            if (source is decimal || source is Int32 || source is double)
            {
                var changeType = Convert.ChangeType("0", typeof(T));
                if (changeType != null)
                    return (T)changeType;
            }
            var type = Convert.ChangeType("", typeof(T));
            if (type != null)
                return (T)type;

            return default(T);
        }

        /// <summary>
        /// Checks the specified expr.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr">The expr.</param>
        /// <returns></returns>
        /// <example>AppUtility.GenericUtil.Check(() => new VERSION_TRAINING_COURSE().TRAINING_COURSE_ID);</example>
        public static string Check<T>(Expression<Func<T>> expr)
        {
            var body = ((MemberExpression)expr.Body);

            //Console.WriteLine("Name is: {0}", body.Member.Name);
            //Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member).GetValue(((ConstantExpression)body.Expression).Value));

            return body.Member.Name;
        }

        /// <summary>
        /// Gets the name of the property.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression">The expression.</param>
        /// <returns></returns>
        public static string GetPropertyName<T>(Expression<Func<T>> expression)
        {
            MemberExpression body = (MemberExpression)expression.Body;

            return body.Member.Name;
        }

        public static string ReadFile(string fullpathFile)
        {
            try
            {
                if (System.IO.File.Exists(fullpathFile))
                {
                    System.IO.StreamReader sr = new StreamReader(fullpathFile, Encoding.UTF8);
                    string data = sr.ReadToEnd();
                    sr.Close();
                    sr.Dispose();
                    return data;
                }
                else
                {
                    return string.Empty;
                }
            }
            catch (System.Exception ex)
            {
                return ex.Message;
            }
            finally
            {

            }

        }

        public static bool SaveFile(string folderpath ,string filename, string content)
        {

            try
            {
                if (!System.IO.Directory.Exists(folderpath))
                {
                    System.IO.Directory.CreateDirectory(folderpath);
                }
                if (System.IO.File.Exists(filename))
                {
                    File.WriteAllText(filename, content);
                    return true;
                }
                else
                {
                    File.WriteAllText(filename, content);
                    return true;
                }
            }
            catch (System.Exception ex)
            {
                return false;
            }
            finally
            {

            }

        }
    }
}
